var App,Page;
/**
 * 顶层对象  App
 * 功能:管理其他所有对象
 */
App = (function(w,$){

    var Request,Router,lifeCycle,Observer,StateMachine;

    /**
     * ajax请求：Request
     * 功能描述：1、在jquery的ajax的基础上扩展接口,除了增加baseUrl属性（接口根目录）外，其他值均跟ajax的options一样，
     * 2、回调方法类似与Promises，不过能力远远不如Promises，后续会赋予更多能力
     * 实现思路：
     */
    Request = (function(){
        var config = {},mode = 'debug';
        function request(options){
            var options = mergeObject(config,options);
            var baseUrl = options.baseUrl || '';
            var url = options.url || '';
            var success = options.success || function(res){};
            var error = options.error || function(res){};
            var complete = options.complete || function(res){};
            options.success = success;
            options.error = error;
            options.complete = complete;
            if(mode == 'debug'){
                options.url = baseUrl;
            }else{
                options.url = baseUrl + url;
            }
            setTimeout(function(){
                $.ajax(options)
            })
            return {
                then:function(fun){
                    options.success = function(res){
                        fun(getResponse(url,res))
                    }
                    return this;
                },
                catch:function(fun){
                    options.error = fun;
                    return this;
                },
                finally:function(fun){
                    options.complete = fun
                    return this;
                }
            }
        }
        function post(options){
            options = options || {};
            options.type = 'POST';
            return request(options);
        }
        function get(options){
            options = options || {};
            options.type = 'GET';
            return request(options);
        }
        function setConfig(options){
            config = options;
            mode = App.mode;
        }
        function getConfig(){
            return config;
        }
        function mergeObject(obj1,obj2){
            var obj = {};
            for(var key in obj1){
                obj[key] = obj1[key];
            }
            for(var key in obj2){
                obj[key] = obj2[key];
            }
            return obj;
        }
        function getResponse(url,res){
            var response = res;
            if(mode == 'debug'){
                var arr = url.split('/');
                for(var i = 0; i < arr.length;i++){
                    response = response[arr[i]]; 
                }
            }
            return response;
        }
        return {
            request:request,
            post:post,
            get:get,
            setConfig,
            getConfig
        }
    }())

    /**
     * 有限转态机对象：State （参考资料 http://www.ruanyifeng.com/blog/2013/09/finite-state_machine_for_javascript.html）
     * 功能描述：通过created创建生成一个有机状态机对象，注册所有状态和对应的执行函数，后续只需要调用setState就可以激活相应的状态
     * 实现思路：状态总数（state）是有限的、任一时刻，只处在一种状态之中、某种条件下，会从一种状态转变（transition）到另一种状态。
     */
    StateMachine = (function(){
        function created(options) {
            if(!(this instanceof created)){
                return new created(options);
            }
            var currentState = null,transitions = [],evens = {start:{},end:{}};

            function setState(state){
                currentState = state;
                return transition();
            } 

            function getState(){
                return currentState;
            }
            //注册事件
            function register(name){
                var funs = evens[name] || {};
                var res = function(){};
                for(var key in funs){
                    var stateFuns = funs[key];
                    if(key === currentState){
                        for(var i = 0; i < stateFuns.length;i++){
                            var fun = stateFuns[i];
                            if(typeof fun === 'function'){
                                res = fun;
                            }
                        }
                    }
                }
                return res;
            }
            //监听事件
            function on(name,state){
                var nameFuns = evens[name] || {};
                var funs = nameFuns[state] || [];
                function fun(fun){
                    funs.push(fun);
                    evens[name][state] = funs;
                    return this;
                }
                return fun;
            }
            //处理状态改变
            function transition (){
                for(var i = 0; i < transitions.length;i++){
                    var state = transitions[i].state;
                    var fun = transitions[i].fun;
                    if(state === currentState){
                        var res = {
                            start:on('start',state),
                            end:on('end',state)
                        }
                        setTimeout(function(){
                            fun({
                                start:register('start'),
                                end:register('end')
                            });
                        })
                        return res;
                    }
                }
            }
            transitions = options.transitions || [];
            currentState = setState(options.state || null);
            this.setState = setState;
            this.getState = getState;
        }
        return {
            created:created
        }
    }())

    /**
     * 观察者对象（发布订阅中心）：Observer （参考资料 http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html）
     * 功能描述：主要用于异步处理，提供发布，订阅，销毁方法
     * 实现思路: 使用list对象存储所有订阅者，key值为订阅者名字，value为function数组
     */
    Observer = (function(){
        //发布订阅事件列表（这里采用对象原因是想用发布的信号当key，订阅的function当value）
        var list = {};
        function _Observer(){
            if(!(this instanceof _Observer)){
                return new _Observer();
            }
        }
        //发布
        _Observer.prototype.publish = function(name){
            for(var key in list){
                if(key == name){
                    var funs = list[key] || [];
                    for(var i = 0;i < funs.length;i++){
                        var res = {
                            arguments:arguments
                        };
                        funs[i](res);
                    }
                }
            }
        }
        //订阅
        _Observer.prototype.subscribe = function(name,fun){
            var funs = null;
            for(var key in list){
                if(key == name){
                    funs = list[key] || [];
                }
            }
            if(funs != null){
                funs.push(fun);
            }else{
                list[name] = [fun];
            }
        }
        //销毁
        _Observer.prototype.unsubscribe = function(name,fun){
            var funs = null;
            for(var key in list){
                if(key == name){
                    funs = list[key] || [];
                }
            }
            if(funs != null){
                list[name] = funs.filter(function(item,i,arr){
                    return fun !== item;
                })
            }
        }
        return _Observer;
    }())

    /**
     * 生命周期对象：lifeCycle
     * 功能描述：为当前注册页面对象处理生命周期
     * 实现思路：
     */
    lifeCycle = (function(){
        function register(page,options){
            page.onLoad(options);
            $(function(){
                page.onReady();
                w.onunload = function(){
                    page.onUnload();
                }; 
            })
        }
        return {
            register:register
        }
    }())

    /**
     * 路由对象：Router
     * 功能描述：管理保存所有页面的page对象，目前仅处理url传参、同时为当前激活的页面对象注册生命周期
     * 实现思路：解析url
     */
    Router = (function(){
        var htmlName = getHtmlName();
        var params = getParams();
        var options = {
            name:htmlName,
            params:params
        };
        var pages = [];
        function add(page){
            console.log(htmlName+'----'+page.name)
            pages.push(page);
            if(htmlName == page.name){
                lifeCycle.register(page,options);
            }
        }
        /**
         * 获取url上的所有字段，并组装成对象抛出
         */
        function getParams(){
            var params = {};
            var search = window.location.search;
            if(search!==''){
                var paramsText = search.split('?')[1] || '';
                var arr = paramsText.split('&');
                for(var i = 0; i < arr.length;i++){
                    var subArr = arr[i].split('=');
                    if(subArr[1]){
                        params[subArr[0]] = subArr[1];
                    }
                }
            }
            return params;
        }
        /**
         * 获取url上的字段值
         */
        function querystring(name){
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", i); // 匹配目标参数
            var result = window.location.search.substr(1).match(reg); // 对querystring匹配目标参数
            if (result != null) {
            return decodeURIComponent(result[2]);
            } else {
            return null;
            }
        }
        /**
         * 获取html名字(过滤参数)
         */
        function getHtmlName(){
            var curPageUrl = window.document.location.href;
            var arr = curPageUrl.split("//")[1].split("/");
            var htmlName = arr[arr.length-1]; 
            var arr = htmlName.split('?');
            if(arr){
                htmlName = arr[0];
            }
            return htmlName;
        }
        return {
            add:add,
            htmlName:getHtmlName,
            getParams:getParams
        }
    }())

    /**
     * 页面对象：Page
     * 功能描述：注册js对象模版
     * 实现思路：1、将options中的所有属性函数都绑定到当前对象,相当与将函数中的this指向改变成当前对象，2、把当前的实例对象添加到router中
     */
    Page = (function(){
        function _Page(options){
            if(!(this instanceof _Page)){
                return new _Page(options);
            }
            if(typeof options === Object && options instanceof Array){
                throw '参数值类型为object'
            }
            if(typeof options.name !== 'string'){
                throw '必须指定页面即name属性'
            }
            for(var key in options){
                var vaue = options[key];
                switch(key){
                    case 'name': this.name = vaue;break;
                    case 'data': this.data = vaue;break;
                    case 'onLoad': this.onLoad = vaue;break;
                    case 'onReady': this.onReady = vaue;break;
                    case 'onUnload': this.onUnload = vaue;break;
                    case 'methods': 
                        var methods = vaue;
                        if(typeof methods === Object && methods instanceof Array) continue;
                        for(var subKey in methods){
                            if(!(methods[subKey] instanceof Function)) continue;
                            this[subKey] = methods[subKey];
                            w[subKey] = methods[subKey].bind(this);
                        }
                        break;
                }
            }
            Router.add(this);
        };
        _Page.prototype.data = {};
        _Page.prototype.methods = {};
        _Page.prototype.onLoad = function(options){};
        _Page.prototype.onReady = function(){};
        _Page.prototype.onUnload = function(){};
        return _Page; 
    }())

    /**
     * 定义App原型
     */
    function _App(options){
        var config = {},mode='debug';
        if(!(this instanceof _App)){
            return new _App(options);
        }else{
            mode = options.mode || 'debug';
            config = options.config || {};
            config = config[mode] || {};
        }
        this.getConfig = function(){
            return config
        }
        //抛出功能对象
        this.window = w;
        this.jQuery = $;
        this.Page = Page;
        this.Router = Router;
        this.Request = Request;
        this.Observer = Observer;
        this.StateMachine= StateMachine;
        this.request = Request.request;
        this.post = Request.post;
        this.get = Request.get;
        _App.mode = mode;
    }
    return _App;
}(window,jQuery))